import 'package:lighthouse/index.dart';

typedef SelectCallback = void Function(FilterItemData itemData);
typedef DismissCallback = void Function();

///Dismiss the popup related to the specific BuildContext
void filterPop(BuildContext context) {
  FilterPopupRoute.pop(context);
}

///Show popup
void filterPopup(
  BuildContext context,
  FilterPopupBaseWidget popupWidget, {
  Offset? offsetLT,
  Offset? offsetRB,
  bool cancelable = true,
  bool outsideTouchCancelable = true,
  bool darkEnable = true,
  Duration duration = const Duration(milliseconds: 200),
}) {
  Navigator.of(context).push(
    FilterPopupRoute(
      popupWidget: popupWidget,
      offsetLT: offsetLT,
      offsetRB: offsetRB,
      cancelable: cancelable,
      outsideTouchCancelable: outsideTouchCancelable,
      darkEnable: darkEnable,
      duration: duration,
    ),
  );
}

mixin FilterPopupBaseWidget implements Widget {
  dismiss();
}

// mixin FilterPopupBaseState implements State {
//   dismiss();
// }

class FilterPopupRoute extends PopupRoute {
  //用来退出
  late FilterPopupBaseWidget popupWidget;

  //偏移值
  late Offset? offsetLT, offsetRB;

  //持续时间
  late Duration duration;

  //取消
  late bool cancelable;

  //点击空白区域取消
  late bool outsideTouchCancelable;

  //
  late bool darkEnable;

  FilterPopupRoute({
    required this.popupWidget,
    this.offsetLT,
    this.offsetRB,
    this.cancelable = true,
    this.outsideTouchCancelable = true,
    this.darkEnable = true,
    this.duration = const Duration(milliseconds: 200),
  }) : super();

  @override
  // TODO: implement barrierColor
  Color? get barrierColor => null;

  @override
  // TODO: implement barrierDismissible
  bool get barrierDismissible => true;

  @override
  // TODO: implement barrierLabel
  String? get barrierLabel => null;

  @override
  Widget buildPage(BuildContext context, Animation<double> animation,
      Animation<double> secondaryAnimation) {
    // TODO: implement buildPage
    return _PopRouteWidget(
      popupWidget: popupWidget,
      offsetLT: offsetLT,
      offsetRB: offsetRB,
      duration: duration,
      cancelable: cancelable,
      outsideTouchCancelable: outsideTouchCancelable,
      darkEnable: darkEnable,
    );
  }

  @override
  // TODO: implement transitionDuration
  Duration get transitionDuration => duration;

  static pop(BuildContext context) {
    _PopRouteWidget.of(context)?.dismiss();
    Navigator.of(context).pop();
  }
}

class _PopRouteWidget extends StatefulWidget {
  final FilterPopupBaseWidget popupWidget;
  final Offset? offsetLT, offsetRB;
  final Duration duration;
  final bool cancelable;
  final bool outsideTouchCancelable;
  final bool darkEnable;

  const _PopRouteWidget({
    Key? key,
    required this.popupWidget,
    this.offsetLT,
    this.offsetRB,
    required this.duration,
    required this.cancelable,
    required this.outsideTouchCancelable,
    required this.darkEnable,
  }) : super(key: key);

  @override
  _PopRouteWidgetState createState() => _PopRouteWidgetState();

  static _PopRouteWidgetState? of(BuildContext context) {
    return context.findAncestorStateOfType<_PopRouteWidgetState>();
  }
}

class _PopRouteWidgetState extends State<_PopRouteWidget>
    with SingleTickerProviderStateMixin {
  late Animation<double> alphaAnim;
  late AnimationController alphaController;

  @override
  void initState() {
    super.initState();
    alphaController = AnimationController(
      vsync: this,
      duration: widget.duration,
    );
    alphaAnim = Tween<double>(begin: 0, end: 127).animate(alphaController);
    alphaController.forward();
  }

  dismiss() {
    alphaController.reverse();
    widget.popupWidget.dismiss();
  }

  @override
  void dispose() {
    alphaController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async {
        if (widget.cancelable) {
          dismiss();
          return true;
        }
        return false;
      },
      child: GestureDetector(
        onTap: () {
          if (widget.outsideTouchCancelable) {
            dismiss();
            Navigator.of(context).pop();
          }
        },
        child: Stack(
          children: <Widget>[
            widget.darkEnable
                ? AnimatedBuilder(
                    animation: alphaController,
                    builder: (_, __) {
                      return Padding(
                        padding: EdgeInsets.only(
                          left: widget.offsetLT?.dx ?? 0,
                          top: widget.offsetLT?.dy ?? 0,
                          right: widget.offsetRB?.dx ?? 0,
                          bottom: widget.offsetRB?.dy ?? 0,
                        ),
                        child: ColorFiltered(
                          colorFilter: ColorFilter.mode(
                            Colors.black.withAlpha(alphaAnim.value.toInt()),
                            BlendMode.srcOut,
                          ),
                          child: Stack(
                            children: _buildDark(),
                          ),
                        ),
                      );
                    },
                  )
                : Container(),
            widget.popupWidget,
          ],
        ),
      ),
    );
  }

  List<Widget> _buildDark() {
    List<Widget> widgets = [];
    widgets.add(Container(
      color: Colors.transparent,
    ));
    return widgets;
  }
}
